package controller

import (
	"net/http"
	"strconv"

	"soma-server/common"
	modelSystem "soma-server/model/system"
	"soma-server/pkg/e"
	r "soma-server/response"
	serviceSystem "soma-server/service/system"
	"soma-server/vo"

	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

type IMenuController interface {
	GetMenuTree(c *gin.Context)          // 获取菜单树结构数据（树形数据表格）
	CreateMenu(c *gin.Context)           // 创建菜单
	UpdateMenuById(c *gin.Context)       // 更新菜单
	BatchDeleteMenuByIds(c *gin.Context) // 批量删除菜单
	GetUserMenuTreeByUserId(c *gin.Context) // 根据用户ID获取用户的权限(可访问)菜单树（左侧菜单栏）
}

type MenuController struct {
	MenuService serviceSystem.IMenuService
}

func NewMenuController() IMenuController {
	menuService := serviceSystem.NewMenuService()
	menuController := MenuController{MenuService: menuService}
	return menuController
}

// 获取菜单树结构数据（树形数据表格）
func (mc MenuController) GetMenuTree(c *gin.Context) {
	menuTree, err := mc.MenuService.GetMenuTree()
	if err != nil {
		common.Log.Errorln("获取菜单树失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_MENU_TREE, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_GET_MENU_TREE, gin.H{
		"tree": menuTree,
	}, true)
}

// 创建菜单
func (mc MenuController) CreateMenu(c *gin.Context) {
	var req vo.CreateMenuRequest
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 获取当前用户
	ur := serviceSystem.NewUserService()
	ctxUser, err := ur.GetCurrentUser(c)
	if err != nil {
		common.Log.Errorln("获取当前用户信息失败")
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_CURRENT_USER, nil, false)
		return
	}

	menu := modelSystem.Menu{
		Name:     &req.Name,
		Path:     req.Path,
		Meta:     req.Meta,
		Redirect: &req.Redirect,
		ParentId: &req.ParentId,
		Creator:  ctxUser.Username,
		Type:     req.Type,
		Status:   &req.Status,
	}

	err = mc.MenuService.CreateMenu(&menu)
	if err != nil {
		common.Log.Errorln("创建菜单失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_CREATE_MENU, nil, false)
		return
	}
	r.Response(c, http.StatusOK, e.SUCCESS_CREATE_MENU, nil, true)
}

// 更新菜单
func (mc MenuController) UpdateMenuById(c *gin.Context) {
	var req vo.UpdateMenuRequest
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}

	// 获取路径中的menuId
	menuId, _ := strconv.Atoi(c.Param("menuId"))
	if menuId <= 0 {
		common.Log.Errorln("菜单ID不正确")
		r.Response(c, http.StatusBadRequest, e.ERROR_MENU_ID_INCORRECT, nil, false)
		return
	}

	// 获取当前用户
	ur := serviceSystem.NewUserService()
	ctxUser, err := ur.GetCurrentUser(c)
	if err != nil {
		common.Log.Errorln("获取当前用户信息失败")
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_CURRENT_USER, nil, false)
		return
	}

	menu := modelSystem.Menu{
		Name:     &req.Name,
		Path:     req.Path,
		Meta:     req.Meta,
		Redirect: &req.Redirect,
		ParentId: &req.ParentId,
		Creator:  ctxUser.Username,
		Type:     req.Type,
		Status:   &req.Status,
	}

	err = mc.MenuService.UpdateMenuById(uint(menuId), &menu)
	if err != nil {
		common.Log.Errorln("更新菜单失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_UPDATE_MENU, nil, false)
		return
	}

	r.Response(c, http.StatusOK, e.SUCCESS_UPDATE_MENU, nil, true)

}

// 批量删除菜单
func (mc MenuController) BatchDeleteMenuByIds(c *gin.Context) {
	var req vo.DeleteMenuRequest
	// 参数绑定
	if err := c.ShouldBind(&req); err != nil {
		common.Log.Errorln(err.Error())
		r.Response(c, http.StatusBadRequest, e.BINDING_PARAMS, nil, false)
		return
	}
	// 参数校验
	if err := common.Validate.Struct(&req); err != nil {
		errStr := err.(validator.ValidationErrors)[0].Translate(common.Trans)
		common.Log.Errorln(errStr)
		r.Response(c, http.StatusBadRequest, e.INVALID_PARAMS, nil, false)
		return
	}
	err := mc.MenuService.BatchDeleteMenuByIds(req.MenuIds)
	if err != nil {
		common.Log.Errorln("删除菜单失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_DELETE_MENU, nil, false)
		return
	}

	r.Response(c, http.StatusOK, e.SUCCESS_DELETE_MENU, nil, true)
}

// 根据用户ID获取用户的权限(可访问)菜单树 --> 左侧菜单栏
func (mc MenuController) GetUserMenuTreeByUserId(c *gin.Context) {
	// 获取路径中的userId
	userId, _ := strconv.Atoi(c.Param("userId"))
	if userId <= 0 {
		common.Log.Errorln("用户ID不正确")
		r.Response(c, http.StatusBadRequest, e.ERROR_USER_ID_NOT_CORRECT, nil, false)
		return
	}

	menuTree, err := mc.MenuService.GetUserMenuTreeByUserId(uint(userId))
	if err != nil {
		common.Log.Errorln("获取用户的可访问菜单树失败: " + err.Error())
		r.Response(c, http.StatusBadRequest, e.ERROR_GET_MENU_TREE_BY_USERID, nil, false)
		return
	}

	r.Response(c, http.StatusOK, e.SUCCESS_GET_MENU_TREE_BY_USERID, menuTree, true)
}
